We will introduce spatial data visualisation tools using the lga_profiles_data_2011_pt1 dataset. We will first produce a choropleth map of Victoria showing the spatial distribution of pertussis incidents, notifications_per_1_000_people_of_pertussis by LGA. Pertussis, more commonly known as whooping cough, is a highly contagious and deadly respiratory infection that affects newborns. The bacterial infection has made a comeback in recent years due to low national immunization rates. The consequences have been deadly. Understanding the spatial distribution of this serious infection can help inform health policy and intervention in an effort to control this preventable infection.

Datasets 1. lga_profiles_data_2011_pt1
2. notifications_per_1_000_people_of_pertussis

Exploratory Data Analysis and Visualization

#install.packages("rgeos") # If required
#install.packages("maptools") # If required
#install.packages("ggmap") # If required
#install.packages("broom") # If required
#install.packages("sf")
#install.packages("rgdal")
library(ggplot2)
package 㤼㸱ggplot2㤼㸲 was built under R version 3.6.3Warning message:
package ‘sp’ was built under R version 3.6.3 
library(dplyr)
package 㤼㸱dplyr㤼㸲 was built under R version 3.6.3
Attaching package: 㤼㸱dplyr㤼㸲

The following objects are masked from 㤼㸱package:stats㤼㸲:

    filter, lag

The following objects are masked from 㤼㸱package:base㤼㸲:

    intersect, setdiff, setequal, union
library(rgeos)
package 㤼㸱rgeos㤼㸲 was built under R version 3.6.3rgeos version: 0.5-3, (SVN revision 634)
 GEOS runtime version: 3.8.0-CAPI-1.13.1 
 Linking to sp version: 1.4-2 
 Polygon checking: TRUE 
library(maptools)
package 㤼㸱maptools㤼㸲 was built under R version 3.6.3Checking rgeos availability: TRUE
library(ggmap)
package 㤼㸱ggmap㤼㸲 was built under R version 3.6.3Google's Terms of Service: https://cloud.google.com/maps-platform/terms/.
Please cite ggmap if you use it! See citation("ggmap") for details.
library(broom)
package 㤼㸱broom㤼㸲 was built under R version 3.6.3
library(sf)
package 㤼㸱sf㤼㸲 was built under R version 3.6.3Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1
library(rgdal)
package 㤼㸱rgdal㤼㸲 was built under R version 3.6.3rgdal: version: 1.5-8, (SVN revision 990)
Geospatial Data Abstraction Library extensions to R successfully loaded
Loaded GDAL runtime: GDAL 3.0.4, released 2020/01/28
Path to GDAL shared files: C:/Users/aminb/OneDrive/Documents/R/win-library/3.6/rgdal/gdal
GDAL binary built with GEOS: TRUE 
Loaded PROJ runtime: Rel. 6.3.1, February 10th, 2020, [PJ_VERSION: 631]
Path to PROJ shared files: C:/Users/aminb/OneDrive/Documents/R/win-library/3.6/rgdal/proj
Linking to sp version:1.4-2
To mute warnings of possible GDAL/OSR exportToProj4() degradation,
use options("rgdal_show_exportToProj4_warnings"="none") before loading rgdal.

Next we import the shape file. To do this correctly you need to import the shape file from a folder with all the contents from vmlite_lga_cm.zip.

vic.lga.shp <- readOGR("data/vmlite_lga_cm.shp")
OGR data source with driver: ESRI Shapefile 
Source: "C:\Users\aminb\OneDrive\Documents\Data Science\Spatial Data Analysis\data\vmlite_lga_cm.shp", layer: "vmlite_lga_cm"
with 91 features
It has 11 fields
Integer64 fields read as strings:  cartodb_id 
# Check
class(vic.lga.shp)
[1] "SpatialPolygonsDataFrame"
attr(,"package")
[1] "sp"
# check columns name
names(vic.lga.shp)
 [1] "ufi"        "ftype_code" "lga_name"   "state"      "scale_usec" "labeluse_c" "ufi_cr"     "lga_name3"  "cartodb_id" "created_at"
[11] "updated_at"
# verify lga_name column
head(vic.lga.shp$lga_name)
[1] SWAN HILL                   TOWONG                      MOUNT BAW BAW ALPINE RESORT SOUTH GIPPSLAND             SOUTHERN GRAMPIANS         
[6] WELLINGTON                 
87 Levels: ALPINE ARARAT BALLARAT BANYULE BASS COAST BAW BAW BAYSIDE BENALLA BOROONDARA BRIMBANK BULOKE CAMPASPE CARDINIA ... YARRIAMBIACK

The code verifies 87 lga_names which is higher than the expected 79. This is because the shp file also includes some islands, resort regions and repeated LGA names.

Now we need to bring in the LGA variables that we would like to map from the lga_profiles_data_2011_pt1.csv dataset. We also want to view the lga_name variable as these will be used as our unique IDs to merge the shp file and the dataset.

lga_profiles_data_2011_pt1 <- read.csv("data/lga_profiles_data_2011_pt1.csv")
head(lga_profiles_data_2011_pt1$lga_name)
[1] ALPINE               ARARAT               BALLARAT             BANYULE              BARWON-SOUTH WESTERN BASS COAST          
90 Levels: ALPINE ARARAT BALLARAT BANYULE BARWON-SOUTH WESTERN BASS COAST BAW BAW BAYSIDE BENALLA BOROONDARA BRIMBANK BULOKE ... YARRIAMBIACK

In order to merge the shp file with the profile data, we need to have matching IDs in both variables.

lga.shp.f <- tidy(vic.lga.shp, region='lga_name')
Unequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vector
head(lga.shp.f)
# Note how the LGA names are now called id. We need to fix this so that both data frames have an lga_name variable to use in the merge.
lga.shp.f$lga_name <- lga.shp.f$id
head(lga.shp.f)

And one, final and very, very important step. We must order the final data frame to be used in the choropleth mapping by merge.lga.profiles$order. This will ensure polygons are drawn correctly in ggplot object.

merge.lga.profiles <- merge(lga.shp.f, lga_profiles_data_2011_pt1,
                            by="lga_name", all.X=TRUE)

And one, final and very, very important step. We must order the final data frame to be used in the choropleth mapping by merge.lga.profiles$order. This will ensure the polygons are drawn correctly in the ggplot object.

choro.data.frame <- merge.lga.profiles[order(merge.lga.profiles$order), ]
#install.packages("mapproj")
library(mapproj)
package 㤼㸱mapproj㤼㸲 was built under R version 3.6.3Loading required package: maps
package 㤼㸱maps㤼㸲 was built under R version 3.6.3

Now we can start with our first plot.

p1 <- ggplot(data = choro.data.frame,
             aes( x=long, y= lat, group=group,
                 fill = notifications_per_1_000_people_of_pertussis))

p1 + geom_polygon(color = "black", size = 0.25) + coord_map() 

# We can make it prettier
p1 + geom_polygon(color="black", size=0.25)+ 
  coord_map()+ 
  scale_fill_distiller(name="Cases \n per 1,000",
                           guide = "legend",
                           palette = "YlOrRd",
                           direction = 1) + 
  theme_minimal() + 
  theme(axis.title.x = element_blank(),
            axis.title.y = element_blank(),
            axis.text.x = element_blank(),
            axis.text.y = element_blank(),
            panel.grid = element_blank()) + 
  labs(title = "VIctorian LGA Pertussis Cases - 2011")

Not bad. It’s a static plot, so we are unable to zoom into Melbourne metro where the majority of Victoria’s population is concentrated. It’s also difficult to see some of the smaller LGA’s and near impossible to see Queenscliff. We could also add some hover information to report the LGA name and exact rate of pertussis cases per 1000 people. We will do this in the following section by introducing Leaflet.

#install.packages("leaflet")
library(leaflet)
package 㤼㸱leaflet㤼㸲 was built under R version 3.6.3

For Leaflet choropleth maps, we need to use a SpatialPolygonDataFrame.

# Check
class(vic.lga.shp)
[1] "SpatialPolygonsDataFrame"
attr(,"package")
[1] "sp"

We can plot the LGA polygons quickly using the leaflet function and addPolyons. We need to set a default view and zoom level.

p2 <- leaflet(vic.lga.shp) %>% 
  setView(lng = 145.5, lat = -36.5, zoom = 5)
p2 %>% addPolygons()

NA

The next step will be to merge the LGA profile data, lga_profiles_data_2011_pt1 with the vic.lga.shp spatial polygon data frame. We use the merge functions from the sp package again. When merging the .shp file directly with the LGA data frame we will encounter errors with duplicated LGAs. To overcome this issue, we can add an argument to duplicate the matches. This won’t impact the choropleth map. Ideally, you would remove the duplicates to ensure a clean merge.

merge.lga.profiles3<-sp::merge(vic.lga.shp, lga_profiles_data_2011_pt1, 
                          by="lga_name", duplicateGeoms = TRUE)

Now we can create a discrete colour scale. There are numerous methods but a simple approach is to base the scale on the quantiles of pertussis notifications. We can use the quantile() and colourBin() function from the leaflet package for this purpose. First, we calculate the quantiles for 5 levels.

bins <- quantile(
  lga_profiles_data_2011_pt1$notifications_per_1_000_people_of_pertussis,
  probs = seq(0,1,.2), names = FALSE, na.rm = TRUE)
bins
[1] 0.09988014 0.76654278 1.04295663 1.40278076 2.07256177 5.59552358

bins now contains five sequential colour levels so that 20% of the data falls within each bin The following histogram visualises the breaks used to create the scale. Note how each bin does not have an equal interval.

ggplot(data = lga_profiles_data_2011_pt1, 
       aes(x = notifications_per_1_000_people_of_pertussis)) +
  geom_histogram(colour = "white", bins = 40) + 
  geom_vline(
    xintercept = quantile(
      lga_profiles_data_2011_pt1$notifications_per_1_000_people_of_pertussis,
      probs = seq(0,1,0.2), na.rm = TRUE), 
    colour = "red", lwd = 1, lty = 2)

bins can be used to create a colour scale, named pal, using the colorBin() function, which maps the bins to a palette. We have selected the YlOrRd palette from the ColourBrewer package.

pal <- colorBin(
  "YlOrRd",
  domain = lga_profiles_data_2011_pt1$notifications_per_1_000_people_of_pertussis, 
  bins = bins
  )

Now we can add the colour scale named pal to the choropleth map. Note how we had to change the dataset to the merged dataset, merge.lga.profiles3.

p3 <- leaflet(merge.lga.profiles3) %>% 
  setView(lng = 147, lat = -36.5, zoom = 6)
p3 %>% addPolygons(
  fillColor = ~pal(notifications_per_1_000_people_of_pertussis),
  weight = 2,
  opacity = 1,
  color = "white",
  dashArray = "3",
  fillOpacity = 0.7)

We can also add highlighting…

p3 %>% addPolygons(
  fillColor = ~pal(notifications_per_1_000_people_of_pertussis),
  weight = 2,
  opacity = 1,
  color = "white",
  dashArray = "3",
  fillOpacity = 0.7,
  highlight = highlightOptions(
    weight = 3,
    color = "#666",
    dashArray = "",
    fillOpacity = 0.7,
    bringToFront = TRUE))

When we hover over an LGA, we should also be able to see the name and pertussis rate.

labels <- sprintf(
  "<strong>%s</strong><br/>%g notifications / 1,000 people",
  merge.lga.profiles3$lga_name, 
  merge.lga.profiles3$notifications_per_1_000_people_of_pertussis
) %>% lapply(htmltools::HTML)

p3 %>% addPolygons(
  fillColor = ~pal(notifications_per_1_000_people_of_pertussis),
  weight = 2,
  opacity = 1,
  color = "white",
  dashArray = "3",
  fillOpacity = 0.7,
  highlight = highlightOptions(
    weight = 5,
    color = "#666",
    dashArray = "",
    fillOpacity = 0.7,
    bringToFront = TRUE),
  label = labels,
  labelOptions = labelOptions(
    style = list("font-weight" = "normal", padding = "3px 8px"),
    textsize = "15px",
    direction = "auto"))

Finally, we need a title and legend.

labels <- sprintf(
  "<strong>%s</strong><br/>%g notifications / 1,000 people",
  merge.lga.profiles3$lga_name, 
  merge.lga.profiles3$notifications_per_1_000_people_of_pertussis
) %>% lapply(htmltools::HTML)

library(htmlwidgets)
package 㤼㸱htmlwidgets㤼㸲 was built under R version 3.6.3
library(htmltools)
package 㤼㸱htmltools㤼㸲 was built under R version 3.6.3
title <- tags$div(
   HTML('<h3>Victorian LGA Pertussis Cases - 2011</h3>')
 )

p3 %>% addPolygons(
  fillColor = ~pal(notifications_per_1_000_people_of_pertussis),
  weight = 2,
  opacity = 1,
  color = "white",
  dashArray = "3",
  fillOpacity = 0.7,
  highlight = highlightOptions(
    weight = 5,
    color = "#666",
    dashArray = "",
    fillOpacity = 0.7,
    bringToFront = TRUE),
  label = labels,
  labelOptions = labelOptions(
    style = list("font-weight" = "normal", padding = "3px 8px"),
    textsize = "15px",
    direction = "auto")) %>% 
  addLegend(pal = pal, 
            values = ~notifications_per_1_000_people_of_pertussis, 
            opacity = 0.7, title = "Notifications /1,000 people",
  position = "bottomright") %>% 
  addControl(title, position = "topright")

Color Scales Changing the colour scale on a choropleth map can have a drastic effect on its appearance. In the following section we will experiment with two other scales - equal intervals and continuous.

Equal intervals use a variable’s minimum and maximum value to define cut points along a variable’s scale that have the same interval. This is the same approach used by a histogram. We use the colourBin() function from the Leaflet package to define the cut points. In this situation, we set bins = 4. You won’t necessarily get 4 bins because Leaflet will try to find a “pretty” number of intervals, which appears to minimise decimal rounding. If you want to force the exact number of bins, insert pretty = FALSE.

pal2 <- colorBin(
  "YlOrRd",
  domain = lga_profiles_data_2011_pt1$notifications_per_1_000_people_of_pertussis,
  bins = 4,
  pretty = FALSE
  )

p3 %>% addPolygons(
  fillColor = ~pal2(notifications_per_1_000_people_of_pertussis),
  weight = 2,
  opacity = 1,
  color = "white",
  dashArray = "3",
  fillOpacity = 0.7,
  highlight = highlightOptions(
    weight = 5,
    color = "#666",
    dashArray = "",
    fillOpacity = 0.7,
    bringToFront = TRUE),
  label = labels,
  labelOptions = labelOptions(
    style = list("font-weight" = "normal", padding = "3px 8px"),
    textsize = "15px",
    direction = "auto")) %>%
  addLegend(pal = pal2,
            values = ~notifications_per_1_000_people_of_pertussis,
            opacity = 0.7, title = "Notifications /1,000 people",
            position = "bottomright") %>%
  addControl(title, position = "topright")

This map is drastically different to the scale based on quantiles. Because pertussis notifications are skewed, the use of an equal interval scale hides the variability in the bulk of the distribution. However, it does do a good job of highlighting outliers, e.g. Corangamite and Central Goldfields.

What about a continuous colour scale? We can try the colorNumeric function from Leaflet.

pal3 <- colorNumeric(
  "YlOrRd",
  domain = lga_profiles_data_2011_pt1$notifications_per_1_000_people_of_pertussis
  )

p3 %>% addPolygons(
  fillColor = ~pal3(notifications_per_1_000_people_of_pertussis),
  weight = 2,
  opacity = 1,
  color = "white",
  dashArray = "3",
  fillOpacity = 0.7,
  highlight = highlightOptions(
    weight = 5,
    color = "#666",
    dashArray = "",
    fillOpacity = 0.7,
    bringToFront = TRUE),
  label = labels,
  labelOptions = labelOptions(
    style = list("font-weight" = "normal", padding = "3px 8px"),
    textsize = "15px",
    direction = "auto")) %>%
  addLegend(pal = pal3,
            values = ~notifications_per_1_000_people_of_pertussis,
            opacity = 0.7, title = "Notifications/1,000 people",
            position = "bottomright") %>%
  addControl(title, position = "topright")

A continuous colour scale is the best option. Due to the skewed nature of the variable, the continuous colour scale highlights the outliers, but provides enough sensitivity in the scale to discern the more subtle differences state-wide.

##Simplify .shp Files When converting .shp to a data.frame, you can sometimes end up with some unusually large datasets. This depends on the .shp file being used. Sometimes their high level of precision (which is needed in mapping) creates a computational problem for spatial data visualisations. Connie Herrity, a former Data Visualisation student, had this very problem. After converting a .shp file to a data.frame she was left with 85.5 million rows. Suffice to say, the map took a prohibitively long time to render. This level of precision is often not needed for data visualisation, so it’s important to have a method to reduce the “resolution” of the .shp file. Connie helped me put together the following section to take you through the process.

We can use the gSimplify() function from the rgeos package.

paste(nrow(lga.shp.f), "rows")
[1] "29285 rows"
print(object.size(lga.shp.f), units="MB")
1.6 Mb

We can now test the effect of gSimplify().

vic.lga.shp.simp1 <- gSimplify(vic.lga.shp, tol = .01, topologyPreserve=TRUE)
vic.lga.shp.simp1 <- SpatialPolygonsDataFrame(vic.lga.shp.simp1,
                                              data=vic.lga.shp@data)
lga.shp.f.simp1 <- tidy(vic.lga.shp.simp1, region = "lga_name")
Unequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vector
print(paste(nrow(lga.shp.f.simp1),"rows"))
[1] "8630 rows"
print(object.size(lga.shp.f.simp1), units = "MB")
0.4 Mb

The tol controls the degree of simplification. Increasing this value will increase the simplification. tol = .01 makes a drastic decrease to the file size, so there is no need to increase this value.

Now, let’s re-plot using the simplified .shp file.

lga.shp.f.simp1$lga_name <- lga.shp.f.simp1$id
merge.lga.profiles2<-merge(lga.shp.f.simp1, lga_profiles_data_2011_pt1,
                          by="lga_name", all.x=TRUE)
choro.data.frame2<-merge.lga.profiles2[order(merge.lga.profiles2$order), ]
p4 <- ggplot(data = choro.data.frame2,
             aes(x = long, y = lat, group = group,
                 fill = notifications_per_1_000_people_of_pertussis))
p4 + geom_polygon(color = "black", size = 0.25) +
  coord_map() +
  scale_fill_distiller(name = "Cases \n per 1,000",
                        guide = "legend",
                    palette = "YlOrRd", direction = 1) +
  theme_minimal() + theme(axis.title.x = element_blank(),
                          axis.title.y = element_blank(),
                          axis.text.x  = element_blank(),
                          axis.text.y  = element_blank(),
                          panel.grid  = element_blank()) +
  labs(title="Victorian LGA Pertussis Cases - 2011")

Now, we would be hard-pressed to notice a difference. This function may save us a lot of trouble when dealing with precision .shp files or optimising a data visualisation app to run smoothly in the cloud.

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

LS0tDQp0aXRsZTogIkNob3JvcGxldGggTWFwIG9mIFBlcnR1c3NpcyBpbmNpZGVudHMgaW4gMjAxMSBvZiBWaWN0b3JpYW4gTG9jYWwgR292ZXJubWVudCBBcmFlKExHQSkiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KV2Ugd2lsbCBpbnRyb2R1Y2Ugc3BhdGlhbCBkYXRhIHZpc3VhbGlzYXRpb24gdG9vbHMgdXNpbmcgdGhlIGBsZ2FfcHJvZmlsZXNfZGF0YV8yMDExX3B0MWAgZGF0YXNldC4gV2Ugd2lsbCBmaXJzdCBwcm9kdWNlIGEgY2hvcm9wbGV0aCBtYXAgb2YgVmljdG9yaWEgc2hvd2luZyB0aGUgc3BhdGlhbCBkaXN0cmlidXRpb24gb2YgcGVydHVzc2lzIGluY2lkZW50cywgYG5vdGlmaWNhdGlvbnNfcGVyXzFfMDAwX3Blb3BsZV9vZl9wZXJ0dXNzaXNgIGJ5IExHQS4gUGVydHVzc2lzLCBtb3JlIGNvbW1vbmx5IGtub3duIGFzIHdob29waW5nIGNvdWdoLCBpcyBhIGhpZ2hseSBjb250YWdpb3VzIGFuZCBkZWFkbHkgcmVzcGlyYXRvcnkgaW5mZWN0aW9uIHRoYXQgYWZmZWN0cyBuZXdib3Jucy4gVGhlIGJhY3RlcmlhbCBpbmZlY3Rpb24gaGFzIG1hZGUgYSBjb21lYmFjayBpbiByZWNlbnQgeWVhcnMgZHVlIHRvIGxvdyBuYXRpb25hbCBpbW11bml6YXRpb24gcmF0ZXMuIFRoZSBjb25zZXF1ZW5jZXMgaGF2ZSBiZWVuIGRlYWRseS4gVW5kZXJzdGFuZGluZyB0aGUgc3BhdGlhbCBkaXN0cmlidXRpb24gb2YgdGhpcyBzZXJpb3VzIGluZmVjdGlvbiBjYW4gaGVscCBpbmZvcm0gaGVhbHRoIHBvbGljeSBhbmQgaW50ZXJ2ZW50aW9uIGluIGFuIGVmZm9ydCB0byBjb250cm9sIHRoaXMgcHJldmVudGFibGUgaW5mZWN0aW9uLg0KDQoqKkRhdGFzZXRzKioNCjEuIGBsZ2FfcHJvZmlsZXNfZGF0YV8yMDExX3B0MWAgPGJyPg0KMi4gYG5vdGlmaWNhdGlvbnNfcGVyXzFfMDAwX3Blb3BsZV9vZl9wZXJ0dXNzaXNgDQoNCioqRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcyBhbmQgVmlzdWFsaXphdGlvbioqDQoNCmBgYHtyfQ0KI2luc3RhbGwucGFja2FnZXMoInJnZW9zIikgIyBJZiByZXF1aXJlZA0KI2luc3RhbGwucGFja2FnZXMoIm1hcHRvb2xzIikgIyBJZiByZXF1aXJlZA0KI2luc3RhbGwucGFja2FnZXMoImdnbWFwIikgIyBJZiByZXF1aXJlZA0KI2luc3RhbGwucGFja2FnZXMoImJyb29tIikgIyBJZiByZXF1aXJlZA0KI2luc3RhbGwucGFja2FnZXMoInNmIikNCiNpbnN0YWxsLnBhY2thZ2VzKCJyZ2RhbCIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShyZ2VvcykNCmxpYnJhcnkobWFwdG9vbHMpDQpsaWJyYXJ5KGdnbWFwKQ0KbGlicmFyeShicm9vbSkNCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KHJnZGFsKQ0KYGBgDQoNCk5leHQgd2UgaW1wb3J0IHRoZSBzaGFwZSBmaWxlLiBUbyBkbyB0aGlzIGNvcnJlY3RseSB5b3UgbmVlZCB0byBpbXBvcnQgdGhlIHNoYXBlIGZpbGUgZnJvbSBhIGZvbGRlciB3aXRoIGFsbCB0aGUgY29udGVudHMgZnJvbSBgdm1saXRlX2xnYV9jbS56aXBgLg0KDQpgYGB7cn0NCnZpYy5sZ2Euc2hwIDwtIHJlYWRPR1IoImRhdGEvdm1saXRlX2xnYV9jbS5zaHAiKQ0KYGBgDQpgYGB7cn0NCiMgQ2hlY2sNCmNsYXNzKHZpYy5sZ2Euc2hwKQ0KYGBgDQpgYGB7cn0NCiMgY2hlY2sgY29sdW1ucyBuYW1lDQpuYW1lcyh2aWMubGdhLnNocCkNCmBgYA0KYGBge3J9DQojIHZlcmlmeSBsZ2FfbmFtZSBjb2x1bW4NCmhlYWQodmljLmxnYS5zaHAkbGdhX25hbWUpDQpgYGANClRoZSBjb2RlIHZlcmlmaWVzIDg3IGBsZ2FfbmFtZXNgIHdoaWNoIGlzIGhpZ2hlciB0aGFuIHRoZSBleHBlY3RlZCA3OS4gVGhpcyBpcyBiZWNhdXNlIHRoZSBzaHAgZmlsZSBhbHNvIGluY2x1ZGVzIHNvbWUgaXNsYW5kcywgcmVzb3J0IHJlZ2lvbnMgYW5kIHJlcGVhdGVkIExHQSBuYW1lcy4NCg0KTm93IHdlIG5lZWQgdG8gYnJpbmcgaW4gdGhlIExHQSB2YXJpYWJsZXMgdGhhdCB3ZSB3b3VsZCBsaWtlIHRvIG1hcCBmcm9tIHRoZSBgbGdhX3Byb2ZpbGVzX2RhdGFfMjAxMV9wdDEuY3N2YCBkYXRhc2V0LiBXZSBhbHNvIHdhbnQgdG8gdmlldyB0aGUgYGxnYV9uYW1lYCB2YXJpYWJsZSBhcyB0aGVzZSB3aWxsIGJlIHVzZWQgYXMgb3VyIHVuaXF1ZSBJRHMgdG8gbWVyZ2UgdGhlIHNocCBmaWxlIGFuZCB0aGUgZGF0YXNldC4NCg0KYGBge3J9DQpsZ2FfcHJvZmlsZXNfZGF0YV8yMDExX3B0MSA8LSByZWFkLmNzdigiZGF0YS9sZ2FfcHJvZmlsZXNfZGF0YV8yMDExX3B0MS5jc3YiKQ0KaGVhZChsZ2FfcHJvZmlsZXNfZGF0YV8yMDExX3B0MSRsZ2FfbmFtZSkNCmBgYA0KDQpJbiBvcmRlciB0byBtZXJnZSB0aGUgc2hwIGZpbGUgd2l0aCB0aGUgcHJvZmlsZSBkYXRhLCB3ZSBuZWVkIHRvIGhhdmUgbWF0Y2hpbmcgSURzIGluIGJvdGggdmFyaWFibGVzLg0KYGBge3J9DQpsZ2Euc2hwLmYgPC0gdGlkeSh2aWMubGdhLnNocCwgcmVnaW9uPSdsZ2FfbmFtZScpDQpoZWFkKGxnYS5zaHAuZikNCmBgYA0KDQoNCg0KYGBge3J9DQojIE5vdGUgaG93IHRoZSBMR0EgbmFtZXMgYXJlIG5vdyBjYWxsZWQgaWQuIFdlIG5lZWQgdG8gZml4IHRoaXMgc28gdGhhdCBib3RoIGRhdGEgZnJhbWVzIGhhdmUgYW4gbGdhX25hbWUgdmFyaWFibGUgdG8gdXNlIGluIHRoZSBtZXJnZS4NCmxnYS5zaHAuZiRsZ2FfbmFtZSA8LSBsZ2Euc2hwLmYkaWQNCmhlYWQobGdhLnNocC5mKQ0KYGBgDQoNCkFuZCBvbmUsIGZpbmFsIGFuZCB2ZXJ5LCB2ZXJ5IGltcG9ydGFudCBzdGVwLiBXZSBtdXN0IG9yZGVyIHRoZSBmaW5hbCBkYXRhIGZyYW1lIHRvIGJlIHVzZWQgaW4gdGhlIGNob3JvcGxldGggbWFwcGluZyBieSBgbWVyZ2UubGdhLnByb2ZpbGVzJG9yZGVyYC4gDQpUaGlzIHdpbGwgZW5zdXJlIHBvbHlnb25zIGFyZSBkcmF3biBjb3JyZWN0bHkgaW4gZ2dwbG90IG9iamVjdC4NCg0KYGBge3J9DQptZXJnZS5sZ2EucHJvZmlsZXMgPC0gbWVyZ2UobGdhLnNocC5mLCBsZ2FfcHJvZmlsZXNfZGF0YV8yMDExX3B0MSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieT0ibGdhX25hbWUiLCBhbGwuWD1UUlVFKQ0KYGBgDQoNCkFuZCBvbmUsIGZpbmFsIGFuZCB2ZXJ5LCB2ZXJ5IGltcG9ydGFudCBzdGVwLiBXZSBtdXN0IG9yZGVyIHRoZSBmaW5hbCBkYXRhIGZyYW1lIHRvIGJlIHVzZWQgaW4gdGhlIGNob3JvcGxldGggbWFwcGluZyBieSBtZXJnZS5sZ2EucHJvZmlsZXMkb3JkZXIuIFRoaXMgd2lsbCBlbnN1cmUgdGhlIHBvbHlnb25zIGFyZSBkcmF3biBjb3JyZWN0bHkgaW4gdGhlIGBnZ3Bsb3RgIG9iamVjdC4NCg0KYGBge3J9DQpjaG9yby5kYXRhLmZyYW1lIDwtIG1lcmdlLmxnYS5wcm9maWxlc1tvcmRlcihtZXJnZS5sZ2EucHJvZmlsZXMkb3JkZXIpLCBdDQoNCmBgYA0KDQpgYGB7cn0NCiNpbnN0YWxsLnBhY2thZ2VzKCJtYXBwcm9qIikNCmxpYnJhcnkobWFwcHJvaikNCmBgYA0KDQpOb3cgd2UgY2FuIHN0YXJ0IHdpdGggb3VyIGZpcnN0IHBsb3QuDQoNCmBgYHtyfQ0KcDEgPC0gZ2dwbG90KGRhdGEgPSBjaG9yby5kYXRhLmZyYW1lLA0KICAgICAgICAgICAgIGFlcyggeD1sb25nLCB5PSBsYXQsIGdyb3VwPWdyb3VwLA0KICAgICAgICAgICAgICAgICBmaWxsID0gbm90aWZpY2F0aW9uc19wZXJfMV8wMDBfcGVvcGxlX29mX3BlcnR1c3NpcykpDQoNCnAxICsgZ2VvbV9wb2x5Z29uKGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDAuMjUpICsgY29vcmRfbWFwKCkgDQpgYGANCmBgYHtyfQ0KIyBXZSBjYW4gbWFrZSBpdCBwcmV0dGllcg0KcDEgKyBnZW9tX3BvbHlnb24oY29sb3I9ImJsYWNrIiwgc2l6ZT0wLjI1KSsgDQogIGNvb3JkX21hcCgpKyANCiAgc2NhbGVfZmlsbF9kaXN0aWxsZXIobmFtZT0iQ2FzZXMgXG4gcGVyIDEsMDAwIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlID0gImxlZ2VuZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gIllsT3JSZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSAxKSArIA0KICB0aGVtZV9taW5pbWFsKCkgKyANCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkpICsgDQogIGxhYnModGl0bGUgPSAiVkljdG9yaWFuIExHQSBQZXJ0dXNzaXMgQ2FzZXMgLSAyMDExIikNCmBgYA0KDQpOb3QgYmFkLiBJdOKAmXMgYSBzdGF0aWMgcGxvdCwgc28gd2UgYXJlIHVuYWJsZSB0byB6b29tIGludG8gTWVsYm91cm5lIG1ldHJvIHdoZXJlIHRoZSBtYWpvcml0eSBvZiBWaWN0b3JpYeKAmXMgcG9wdWxhdGlvbiBpcyBjb25jZW50cmF0ZWQuIEl04oCZcyBhbHNvIGRpZmZpY3VsdCB0byBzZWUgc29tZSBvZiB0aGUgc21hbGxlciBMR0HigJlzIGFuZCBuZWFyIGltcG9zc2libGUgdG8gc2VlIFF1ZWVuc2NsaWZmLiBXZSBjb3VsZCBhbHNvIGFkZCBzb21lIGhvdmVyIGluZm9ybWF0aW9uIHRvIHJlcG9ydCB0aGUgTEdBIG5hbWUgYW5kIGV4YWN0IHJhdGUgb2YgcGVydHVzc2lzIGNhc2VzIHBlciAxMDAwIHBlb3BsZS4gV2Ugd2lsbCBkbyB0aGlzIGluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbiBieSBpbnRyb2R1Y2luZyBMZWFmbGV0Lg0KDQpgYGB7cn0NCiNpbnN0YWxsLnBhY2thZ2VzKCJsZWFmbGV0IikNCmxpYnJhcnkobGVhZmxldCkNCmBgYA0KDQpGb3IgTGVhZmxldCBjaG9yb3BsZXRoIG1hcHMsIHdlIG5lZWQgdG8gdXNlIGEgU3BhdGlhbFBvbHlnb25EYXRhRnJhbWUuDQoNCmBgYHtyfQ0KIyBDaGVjaw0KY2xhc3ModmljLmxnYS5zaHApDQpgYGANCg0KV2UgY2FuIHBsb3QgdGhlIExHQSBwb2x5Z29ucyBxdWlja2x5IHVzaW5nIHRoZSBsZWFmbGV0IGZ1bmN0aW9uIGFuZCBhZGRQb2x5b25zLiBXZSBuZWVkIHRvIHNldCBhIGRlZmF1bHQgdmlldyBhbmQgem9vbSBsZXZlbC4gDQoNCmBgYHtyfQ0KcDIgPC0gbGVhZmxldCh2aWMubGdhLnNocCkgJT4lIA0KICBzZXRWaWV3KGxuZyA9IDE0NS41LCBsYXQgPSAtMzYuNSwgem9vbSA9IDUpDQpwMiAlPiUgYWRkUG9seWdvbnMoKQ0KDQpgYGANCg0KVGhlIG5leHQgc3RlcCB3aWxsIGJlIHRvIG1lcmdlIHRoZSBMR0EgcHJvZmlsZSBkYXRhLCBsZ2FfcHJvZmlsZXNfZGF0YV8yMDExX3B0MSB3aXRoIHRoZSB2aWMubGdhLnNocCBzcGF0aWFsIHBvbHlnb24gZGF0YSBmcmFtZS4NCldlIHVzZSB0aGUgbWVyZ2UgZnVuY3Rpb25zIGZyb20gdGhlIHNwIHBhY2thZ2UgYWdhaW4uIFdoZW4gbWVyZ2luZyB0aGUgLnNocCBmaWxlIGRpcmVjdGx5IHdpdGggdGhlIExHQSBkYXRhIGZyYW1lIHdlIHdpbGwgZW5jb3VudGVyIGVycm9ycyB3aXRoIGR1cGxpY2F0ZWQgTEdBcy4gVG8gb3ZlcmNvbWUgdGhpcyBpc3N1ZSwgd2UgY2FuIGFkZCBhbiBhcmd1bWVudCB0byBkdXBsaWNhdGUgdGhlIG1hdGNoZXMuIFRoaXMgd29u4oCZdCBpbXBhY3QgdGhlIGNob3JvcGxldGggbWFwLiBJZGVhbGx5LCB5b3Ugd291bGQgcmVtb3ZlIHRoZSBkdXBsaWNhdGVzIHRvIGVuc3VyZSBhIGNsZWFuIG1lcmdlLg0KDQpgYGB7cn0NCm1lcmdlLmxnYS5wcm9maWxlczM8LXNwOjptZXJnZSh2aWMubGdhLnNocCwgbGdhX3Byb2ZpbGVzX2RhdGFfMjAxMV9wdDEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBieT0ibGdhX25hbWUiLCBkdXBsaWNhdGVHZW9tcyA9IFRSVUUpDQpgYGANCg0KTm93IHdlIGNhbiBjcmVhdGUgYSBkaXNjcmV0ZSBjb2xvdXIgc2NhbGUuIFRoZXJlIGFyZSBudW1lcm91cyBtZXRob2RzIGJ1dCBhIHNpbXBsZSBhcHByb2FjaCBpcyB0byBiYXNlIHRoZSBzY2FsZSBvbiB0aGUgcXVhbnRpbGVzIG9mIHBlcnR1c3NpcyBub3RpZmljYXRpb25zLiBXZSBjYW4gdXNlIHRoZSBxdWFudGlsZSgpIGFuZCBjb2xvdXJCaW4oKSBmdW5jdGlvbiBmcm9tIHRoZSBsZWFmbGV0IHBhY2thZ2UgZm9yIHRoaXMgcHVycG9zZS4gRmlyc3QsIHdlIGNhbGN1bGF0ZSB0aGUgcXVhbnRpbGVzIGZvciA1IGxldmVscy4NCg0KYGBge3J9DQpiaW5zIDwtIHF1YW50aWxlKA0KICBsZ2FfcHJvZmlsZXNfZGF0YV8yMDExX3B0MSRub3RpZmljYXRpb25zX3Blcl8xXzAwMF9wZW9wbGVfb2ZfcGVydHVzc2lzLA0KICBwcm9icyA9IHNlcSgwLDEsLjIpLCBuYW1lcyA9IEZBTFNFLCBuYS5ybSA9IFRSVUUpDQpiaW5zDQpgYGANCg0KYmlucyBub3cgY29udGFpbnMgZml2ZSBzZXF1ZW50aWFsIGNvbG91ciBsZXZlbHMgc28gdGhhdCAyMCUgb2YgdGhlIGRhdGEgZmFsbHMgd2l0aGluIGVhY2ggYmluIFRoZSBmb2xsb3dpbmcgaGlzdG9ncmFtIHZpc3VhbGlzZXMgdGhlIGJyZWFrcyB1c2VkIHRvIGNyZWF0ZSB0aGUgc2NhbGUuIE5vdGUgaG93IGVhY2ggYmluIGRvZXMgbm90IGhhdmUgYW4gZXF1YWwgaW50ZXJ2YWwuDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBsZ2FfcHJvZmlsZXNfZGF0YV8yMDExX3B0MSwgDQogICAgICAgYWVzKHggPSBub3RpZmljYXRpb25zX3Blcl8xXzAwMF9wZW9wbGVfb2ZfcGVydHVzc2lzKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShjb2xvdXIgPSAid2hpdGUiLCBiaW5zID0gNDApICsgDQogIGdlb21fdmxpbmUoDQogICAgeGludGVyY2VwdCA9IHF1YW50aWxlKA0KICAgICAgbGdhX3Byb2ZpbGVzX2RhdGFfMjAxMV9wdDEkbm90aWZpY2F0aW9uc19wZXJfMV8wMDBfcGVvcGxlX29mX3BlcnR1c3NpcywNCiAgICAgIHByb2JzID0gc2VxKDAsMSwwLjIpLCBuYS5ybSA9IFRSVUUpLCANCiAgICBjb2xvdXIgPSAicmVkIiwgbHdkID0gMSwgbHR5ID0gMikNCmBgYA0KDQpiaW5zIGNhbiBiZSB1c2VkIHRvIGNyZWF0ZSBhIGNvbG91ciBzY2FsZSwgbmFtZWQgcGFsLCB1c2luZyB0aGUgY29sb3JCaW4oKSBmdW5jdGlvbiwgd2hpY2ggbWFwcyB0aGUgYmlucyB0byBhIHBhbGV0dGUuIFdlIGhhdmUgc2VsZWN0ZWQgdGhlIFlsT3JSZCBwYWxldHRlIGZyb20gdGhlIENvbG91ckJyZXdlciBwYWNrYWdlLg0KDQpgYGB7cn0NCnBhbCA8LSBjb2xvckJpbigNCiAgIllsT3JSZCIsDQogIGRvbWFpbiA9IGxnYV9wcm9maWxlc19kYXRhXzIwMTFfcHQxJG5vdGlmaWNhdGlvbnNfcGVyXzFfMDAwX3Blb3BsZV9vZl9wZXJ0dXNzaXMsIA0KICBiaW5zID0gYmlucw0KICApDQpgYGANCg0KTm93IHdlIGNhbiBhZGQgdGhlIGNvbG91ciBzY2FsZSBuYW1lZCBwYWwgdG8gdGhlIGNob3JvcGxldGggbWFwLiBOb3RlIGhvdyB3ZSBoYWQgdG8gY2hhbmdlIHRoZSBkYXRhc2V0IHRvIHRoZSBtZXJnZWQgZGF0YXNldCwgbWVyZ2UubGdhLnByb2ZpbGVzMy4NCg0KYGBge3J9DQpwMyA8LSBsZWFmbGV0KG1lcmdlLmxnYS5wcm9maWxlczMpICU+JSANCiAgc2V0VmlldyhsbmcgPSAxNDcsIGxhdCA9IC0zNi41LCB6b29tID0gNikNCnAzICU+JSBhZGRQb2x5Z29ucygNCiAgZmlsbENvbG9yID0gfnBhbChub3RpZmljYXRpb25zX3Blcl8xXzAwMF9wZW9wbGVfb2ZfcGVydHVzc2lzKSwNCiAgd2VpZ2h0ID0gMiwNCiAgb3BhY2l0eSA9IDEsDQogIGNvbG9yID0gIndoaXRlIiwNCiAgZGFzaEFycmF5ID0gIjMiLA0KICBmaWxsT3BhY2l0eSA9IDAuNykNCmBgYA0KDQpXZSBjYW4gYWxzbyBhZGQgaGlnaGxpZ2h0aW5n4oCmDQoNCmBgYHtyfQ0KcDMgJT4lIGFkZFBvbHlnb25zKA0KICBmaWxsQ29sb3IgPSB+cGFsKG5vdGlmaWNhdGlvbnNfcGVyXzFfMDAwX3Blb3BsZV9vZl9wZXJ0dXNzaXMpLA0KICB3ZWlnaHQgPSAyLA0KICBvcGFjaXR5ID0gMSwNCiAgY29sb3IgPSAid2hpdGUiLA0KICBkYXNoQXJyYXkgPSAiMyIsDQogIGZpbGxPcGFjaXR5ID0gMC43LA0KICBoaWdobGlnaHQgPSBoaWdobGlnaHRPcHRpb25zKA0KICAgIHdlaWdodCA9IDMsDQogICAgY29sb3IgPSAiIzY2NiIsDQogICAgZGFzaEFycmF5ID0gIiIsDQogICAgZmlsbE9wYWNpdHkgPSAwLjcsDQogICAgYnJpbmdUb0Zyb250ID0gVFJVRSkpDQpgYGANCg0KV2hlbiB3ZSBob3ZlciBvdmVyIGFuIExHQSwgd2Ugc2hvdWxkIGFsc28gYmUgYWJsZSB0byBzZWUgdGhlIG5hbWUgYW5kIHBlcnR1c3NpcyByYXRlLg0KDQpgYGB7cn0NCmxhYmVscyA8LSBzcHJpbnRmKA0KICAiPHN0cm9uZz4lczwvc3Ryb25nPjxici8+JWcgbm90aWZpY2F0aW9ucyAvIDEsMDAwIHBlb3BsZSIsDQogIG1lcmdlLmxnYS5wcm9maWxlczMkbGdhX25hbWUsIA0KICBtZXJnZS5sZ2EucHJvZmlsZXMzJG5vdGlmaWNhdGlvbnNfcGVyXzFfMDAwX3Blb3BsZV9vZl9wZXJ0dXNzaXMNCikgJT4lIGxhcHBseShodG1sdG9vbHM6OkhUTUwpDQoNCnAzICU+JSBhZGRQb2x5Z29ucygNCiAgZmlsbENvbG9yID0gfnBhbChub3RpZmljYXRpb25zX3Blcl8xXzAwMF9wZW9wbGVfb2ZfcGVydHVzc2lzKSwNCiAgd2VpZ2h0ID0gMiwNCiAgb3BhY2l0eSA9IDEsDQogIGNvbG9yID0gIndoaXRlIiwNCiAgZGFzaEFycmF5ID0gIjMiLA0KICBmaWxsT3BhY2l0eSA9IDAuNywNCiAgaGlnaGxpZ2h0ID0gaGlnaGxpZ2h0T3B0aW9ucygNCiAgICB3ZWlnaHQgPSA1LA0KICAgIGNvbG9yID0gIiM2NjYiLA0KICAgIGRhc2hBcnJheSA9ICIiLA0KICAgIGZpbGxPcGFjaXR5ID0gMC43LA0KICAgIGJyaW5nVG9Gcm9udCA9IFRSVUUpLA0KICBsYWJlbCA9IGxhYmVscywNCiAgbGFiZWxPcHRpb25zID0gbGFiZWxPcHRpb25zKA0KICAgIHN0eWxlID0gbGlzdCgiZm9udC13ZWlnaHQiID0gIm5vcm1hbCIsIHBhZGRpbmcgPSAiM3B4IDhweCIpLA0KICAgIHRleHRzaXplID0gIjE1cHgiLA0KICAgIGRpcmVjdGlvbiA9ICJhdXRvIikpDQpgYGANCg0KRmluYWxseSwgd2UgbmVlZCBhIHRpdGxlIGFuZCBsZWdlbmQuDQoNCmBgYHtyfQ0KbGFiZWxzIDwtIHNwcmludGYoDQogICI8c3Ryb25nPiVzPC9zdHJvbmc+PGJyLz4lZyBub3RpZmljYXRpb25zIC8gMSwwMDAgcGVvcGxlIiwNCiAgbWVyZ2UubGdhLnByb2ZpbGVzMyRsZ2FfbmFtZSwgDQogIG1lcmdlLmxnYS5wcm9maWxlczMkbm90aWZpY2F0aW9uc19wZXJfMV8wMDBfcGVvcGxlX29mX3BlcnR1c3Npcw0KKSAlPiUgbGFwcGx5KGh0bWx0b29sczo6SFRNTCkNCg0KbGlicmFyeShodG1sd2lkZ2V0cykNCmxpYnJhcnkoaHRtbHRvb2xzKQ0KDQp0aXRsZSA8LSB0YWdzJGRpdigNCiAgIEhUTUwoJzxoMz5WaWN0b3JpYW4gTEdBIFBlcnR1c3NpcyBDYXNlcyAtIDIwMTE8L2gzPicpDQogKQ0KDQpwMyAlPiUgYWRkUG9seWdvbnMoDQogIGZpbGxDb2xvciA9IH5wYWwobm90aWZpY2F0aW9uc19wZXJfMV8wMDBfcGVvcGxlX29mX3BlcnR1c3NpcyksDQogIHdlaWdodCA9IDIsDQogIG9wYWNpdHkgPSAxLA0KICBjb2xvciA9ICJ3aGl0ZSIsDQogIGRhc2hBcnJheSA9ICIzIiwNCiAgZmlsbE9wYWNpdHkgPSAwLjcsDQogIGhpZ2hsaWdodCA9IGhpZ2hsaWdodE9wdGlvbnMoDQogICAgd2VpZ2h0ID0gNSwNCiAgICBjb2xvciA9ICIjNjY2IiwNCiAgICBkYXNoQXJyYXkgPSAiIiwNCiAgICBmaWxsT3BhY2l0eSA9IDAuNywNCiAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSwNCiAgbGFiZWwgPSBsYWJlbHMsDQogIGxhYmVsT3B0aW9ucyA9IGxhYmVsT3B0aW9ucygNCiAgICBzdHlsZSA9IGxpc3QoImZvbnQtd2VpZ2h0IiA9ICJub3JtYWwiLCBwYWRkaW5nID0gIjNweCA4cHgiKSwNCiAgICB0ZXh0c2l6ZSA9ICIxNXB4IiwNCiAgICBkaXJlY3Rpb24gPSAiYXV0byIpKSAlPiUgDQogIGFkZExlZ2VuZChwYWwgPSBwYWwsIA0KICAgICAgICAgICAgdmFsdWVzID0gfm5vdGlmaWNhdGlvbnNfcGVyXzFfMDAwX3Blb3BsZV9vZl9wZXJ0dXNzaXMsIA0KICAgICAgICAgICAgb3BhY2l0eSA9IDAuNywgdGl0bGUgPSAiTm90aWZpY2F0aW9ucyAvMSwwMDAgcGVvcGxlIiwNCiAgcG9zaXRpb24gPSAiYm90dG9tcmlnaHQiKSAlPiUgDQogIGFkZENvbnRyb2wodGl0bGUsIHBvc2l0aW9uID0gInRvcHJpZ2h0IikNCmBgYA0KDQoqQ29sb3IgU2NhbGVzKg0KQ2hhbmdpbmcgdGhlIGNvbG91ciBzY2FsZSBvbiBhIGNob3JvcGxldGggbWFwIGNhbiBoYXZlIGEgZHJhc3RpYyBlZmZlY3Qgb24gaXRzIGFwcGVhcmFuY2UuIEluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbiB3ZSB3aWxsIGV4cGVyaW1lbnQgd2l0aCB0d28gb3RoZXIgc2NhbGVzIC0gZXF1YWwgaW50ZXJ2YWxzIGFuZCBjb250aW51b3VzLg0KDQoqRXF1YWwgaW50ZXJ2YWxzKiB1c2UgYSB2YXJpYWJsZeKAmXMgbWluaW11bSBhbmQgbWF4aW11bSB2YWx1ZSB0byBkZWZpbmUgY3V0IHBvaW50cyBhbG9uZyBhIHZhcmlhYmxl4oCZcyBzY2FsZSB0aGF0IGhhdmUgdGhlIHNhbWUgaW50ZXJ2YWwuIFRoaXMgaXMgdGhlIHNhbWUgYXBwcm9hY2ggdXNlZCBieSBhIGhpc3RvZ3JhbS4gV2UgdXNlIHRoZSBjb2xvdXJCaW4oKSBmdW5jdGlvbiBmcm9tIHRoZSBMZWFmbGV0IHBhY2thZ2UgdG8gZGVmaW5lIHRoZSBjdXQgcG9pbnRzLiBJbiB0aGlzIHNpdHVhdGlvbiwgd2Ugc2V0IGJpbnMgPSA0LiBZb3Ugd29u4oCZdCBuZWNlc3NhcmlseSBnZXQgNCBiaW5zIGJlY2F1c2UgTGVhZmxldCB3aWxsIHRyeSB0byBmaW5kIGEg4oCccHJldHR54oCdIG51bWJlciBvZiBpbnRlcnZhbHMsIHdoaWNoIGFwcGVhcnMgdG8gbWluaW1pc2UgZGVjaW1hbCByb3VuZGluZy4gSWYgeW91IHdhbnQgdG8gZm9yY2UgdGhlIGV4YWN0IG51bWJlciBvZiBiaW5zLCBpbnNlcnQgcHJldHR5ID0gRkFMU0UuDQoNCmBgYHtyfQ0KcGFsMiA8LSBjb2xvckJpbigNCiAgIllsT3JSZCIsDQogIGRvbWFpbiA9IGxnYV9wcm9maWxlc19kYXRhXzIwMTFfcHQxJG5vdGlmaWNhdGlvbnNfcGVyXzFfMDAwX3Blb3BsZV9vZl9wZXJ0dXNzaXMsDQogIGJpbnMgPSA0LA0KICBwcmV0dHkgPSBGQUxTRQ0KICApDQoNCnAzICU+JSBhZGRQb2x5Z29ucygNCiAgZmlsbENvbG9yID0gfnBhbDIobm90aWZpY2F0aW9uc19wZXJfMV8wMDBfcGVvcGxlX29mX3BlcnR1c3NpcyksDQogIHdlaWdodCA9IDIsDQogIG9wYWNpdHkgPSAxLA0KICBjb2xvciA9ICJ3aGl0ZSIsDQogIGRhc2hBcnJheSA9ICIzIiwNCiAgZmlsbE9wYWNpdHkgPSAwLjcsDQogIGhpZ2hsaWdodCA9IGhpZ2hsaWdodE9wdGlvbnMoDQogICAgd2VpZ2h0ID0gNSwNCiAgICBjb2xvciA9ICIjNjY2IiwNCiAgICBkYXNoQXJyYXkgPSAiIiwNCiAgICBmaWxsT3BhY2l0eSA9IDAuNywNCiAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSwNCiAgbGFiZWwgPSBsYWJlbHMsDQogIGxhYmVsT3B0aW9ucyA9IGxhYmVsT3B0aW9ucygNCiAgICBzdHlsZSA9IGxpc3QoImZvbnQtd2VpZ2h0IiA9ICJub3JtYWwiLCBwYWRkaW5nID0gIjNweCA4cHgiKSwNCiAgICB0ZXh0c2l6ZSA9ICIxNXB4IiwNCiAgICBkaXJlY3Rpb24gPSAiYXV0byIpKSAlPiUNCiAgYWRkTGVnZW5kKHBhbCA9IHBhbDIsDQogICAgICAgICAgICB2YWx1ZXMgPSB+bm90aWZpY2F0aW9uc19wZXJfMV8wMDBfcGVvcGxlX29mX3BlcnR1c3NpcywNCiAgICAgICAgICAgIG9wYWNpdHkgPSAwLjcsIHRpdGxlID0gIk5vdGlmaWNhdGlvbnMgLzEsMDAwIHBlb3BsZSIsDQogICAgICAgICAgICBwb3NpdGlvbiA9ICJib3R0b21yaWdodCIpICU+JQ0KICBhZGRDb250cm9sKHRpdGxlLCBwb3NpdGlvbiA9ICJ0b3ByaWdodCIpDQpgYGANCg0KVGhpcyBtYXAgaXMgZHJhc3RpY2FsbHkgZGlmZmVyZW50IHRvIHRoZSBzY2FsZSBiYXNlZCBvbiBxdWFudGlsZXMuIEJlY2F1c2UgcGVydHVzc2lzIG5vdGlmaWNhdGlvbnMgYXJlIHNrZXdlZCwgdGhlIHVzZSBvZiBhbiBlcXVhbCBpbnRlcnZhbCBzY2FsZSBoaWRlcyB0aGUgdmFyaWFiaWxpdHkgaW4gdGhlIGJ1bGsgb2YgdGhlIGRpc3RyaWJ1dGlvbi4gSG93ZXZlciwgaXQgZG9lcyBkbyBhIGdvb2Qgam9iIG9mIGhpZ2hsaWdodGluZyBvdXRsaWVycywgZS5nLiBDb3JhbmdhbWl0ZSBhbmQgQ2VudHJhbCBHb2xkZmllbGRzLg0KDQpXaGF0IGFib3V0IGEgY29udGludW91cyBjb2xvdXIgc2NhbGU/IFdlIGNhbiB0cnkgdGhlICpjb2xvck51bWVyaWMqIGZ1bmN0aW9uIGZyb20gTGVhZmxldC4NCg0KYGBge3J9DQpwYWwzIDwtIGNvbG9yTnVtZXJpYygNCiAgIllsT3JSZCIsDQogIGRvbWFpbiA9IGxnYV9wcm9maWxlc19kYXRhXzIwMTFfcHQxJG5vdGlmaWNhdGlvbnNfcGVyXzFfMDAwX3Blb3BsZV9vZl9wZXJ0dXNzaXMNCiAgKQ0KDQpwMyAlPiUgYWRkUG9seWdvbnMoDQogIGZpbGxDb2xvciA9IH5wYWwzKG5vdGlmaWNhdGlvbnNfcGVyXzFfMDAwX3Blb3BsZV9vZl9wZXJ0dXNzaXMpLA0KICB3ZWlnaHQgPSAyLA0KICBvcGFjaXR5ID0gMSwNCiAgY29sb3IgPSAid2hpdGUiLA0KICBkYXNoQXJyYXkgPSAiMyIsDQogIGZpbGxPcGFjaXR5ID0gMC43LA0KICBoaWdobGlnaHQgPSBoaWdobGlnaHRPcHRpb25zKA0KICAgIHdlaWdodCA9IDUsDQogICAgY29sb3IgPSAiIzY2NiIsDQogICAgZGFzaEFycmF5ID0gIiIsDQogICAgZmlsbE9wYWNpdHkgPSAwLjcsDQogICAgYnJpbmdUb0Zyb250ID0gVFJVRSksDQogIGxhYmVsID0gbGFiZWxzLA0KICBsYWJlbE9wdGlvbnMgPSBsYWJlbE9wdGlvbnMoDQogICAgc3R5bGUgPSBsaXN0KCJmb250LXdlaWdodCIgPSAibm9ybWFsIiwgcGFkZGluZyA9ICIzcHggOHB4IiksDQogICAgdGV4dHNpemUgPSAiMTVweCIsDQogICAgZGlyZWN0aW9uID0gImF1dG8iKSkgJT4lDQogIGFkZExlZ2VuZChwYWwgPSBwYWwzLA0KICAgICAgICAgICAgdmFsdWVzID0gfm5vdGlmaWNhdGlvbnNfcGVyXzFfMDAwX3Blb3BsZV9vZl9wZXJ0dXNzaXMsDQogICAgICAgICAgICBvcGFjaXR5ID0gMC43LCB0aXRsZSA9ICJOb3RpZmljYXRpb25zLzEsMDAwIHBlb3BsZSIsDQogICAgICAgICAgICBwb3NpdGlvbiA9ICJib3R0b21yaWdodCIpICU+JQ0KICBhZGRDb250cm9sKHRpdGxlLCBwb3NpdGlvbiA9ICJ0b3ByaWdodCIpDQpgYGANCg0KQSAqY29udGludW91cyBjb2xvdXIgc2NhbGUqIGlzIHRoZSBiZXN0IG9wdGlvbi4gRHVlIHRvIHRoZSBza2V3ZWQgbmF0dXJlIG9mIHRoZSB2YXJpYWJsZSwgdGhlIGNvbnRpbnVvdXMgY29sb3VyIHNjYWxlIGhpZ2hsaWdodHMgdGhlIG91dGxpZXJzLCBidXQgcHJvdmlkZXMgZW5vdWdoIHNlbnNpdGl2aXR5IGluIHRoZSBzY2FsZSB0byBkaXNjZXJuIHRoZSBtb3JlIHN1YnRsZSBkaWZmZXJlbmNlcyBzdGF0ZS13aWRlLg0KDQojI1NpbXBsaWZ5IC5zaHAgRmlsZXMNCldoZW4gY29udmVydGluZyAuc2hwIHRvIGEgZGF0YS5mcmFtZSwgeW91IGNhbiBzb21ldGltZXMgZW5kIHVwIHdpdGggc29tZSB1bnVzdWFsbHkgbGFyZ2UgZGF0YXNldHMuIFRoaXMgZGVwZW5kcyBvbiB0aGUgLnNocCBmaWxlIGJlaW5nIHVzZWQuIFNvbWV0aW1lcyB0aGVpciBoaWdoIGxldmVsIG9mIHByZWNpc2lvbiAod2hpY2ggaXMgbmVlZGVkIGluIG1hcHBpbmcpIGNyZWF0ZXMgYSBjb21wdXRhdGlvbmFsIHByb2JsZW0gZm9yIHNwYXRpYWwgZGF0YSB2aXN1YWxpc2F0aW9ucy4gQ29ubmllIEhlcnJpdHksIGEgZm9ybWVyIERhdGEgVmlzdWFsaXNhdGlvbiBzdHVkZW50LCBoYWQgdGhpcyB2ZXJ5IHByb2JsZW0uIEFmdGVyIGNvbnZlcnRpbmcgYSAuc2hwIGZpbGUgdG8gYSBkYXRhLmZyYW1lIHNoZSB3YXMgbGVmdCB3aXRoIDg1LjUgbWlsbGlvbiByb3dzLiBTdWZmaWNlIHRvIHNheSwgdGhlIG1hcCB0b29rIGEgcHJvaGliaXRpdmVseSBsb25nIHRpbWUgdG8gcmVuZGVyLiBUaGlzIGxldmVsIG9mIHByZWNpc2lvbiBpcyBvZnRlbiBub3QgbmVlZGVkIGZvciBkYXRhIHZpc3VhbGlzYXRpb24sIHNvIGl04oCZcyBpbXBvcnRhbnQgdG8gaGF2ZSBhIG1ldGhvZCB0byByZWR1Y2UgdGhlIOKAnHJlc29sdXRpb27igJ0gb2YgdGhlIC5zaHAgZmlsZS4gQ29ubmllIGhlbHBlZCBtZSBwdXQgdG9nZXRoZXIgdGhlIGZvbGxvd2luZyBzZWN0aW9uIHRvIHRha2UgeW91IHRocm91Z2ggdGhlIHByb2Nlc3MuDQoNCiBXZSBjYW4gdXNlIHRoZSBgZ1NpbXBsaWZ5KClgIGZ1bmN0aW9uIGZyb20gdGhlIGByZ2Vvc2AgcGFja2FnZS4NCiANCmBgYHtyfQ0KcGFzdGUobnJvdyhsZ2Euc2hwLmYpLCAicm93cyIpDQpgYGANCiANCmBgYHtyfQ0KcHJpbnQob2JqZWN0LnNpemUobGdhLnNocC5mKSwgdW5pdHM9Ik1CIikNCmBgYA0KDQpXZSBjYW4gbm93IHRlc3QgdGhlIGVmZmVjdCBvZiBgZ1NpbXBsaWZ5KClgLg0KDQpgYGB7cn0NCnZpYy5sZ2Euc2hwLnNpbXAxIDwtIGdTaW1wbGlmeSh2aWMubGdhLnNocCwgdG9sID0gLjAxLCB0b3BvbG9neVByZXNlcnZlPVRSVUUpDQp2aWMubGdhLnNocC5zaW1wMSA8LSBTcGF0aWFsUG9seWdvbnNEYXRhRnJhbWUodmljLmxnYS5zaHAuc2ltcDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT12aWMubGdhLnNocEBkYXRhKQ0KbGdhLnNocC5mLnNpbXAxIDwtIHRpZHkodmljLmxnYS5zaHAuc2ltcDEsIHJlZ2lvbiA9ICJsZ2FfbmFtZSIpDQpwcmludChwYXN0ZShucm93KGxnYS5zaHAuZi5zaW1wMSksInJvd3MiKSkNCg0KcHJpbnQob2JqZWN0LnNpemUobGdhLnNocC5mLnNpbXAxKSwgdW5pdHMgPSAiTUIiKQ0KYGBgDQoNClRoZSBgdG9sYCBjb250cm9scyB0aGUgZGVncmVlIG9mIHNpbXBsaWZpY2F0aW9uLiBJbmNyZWFzaW5nIHRoaXMgdmFsdWUgd2lsbCBpbmNyZWFzZSB0aGUgc2ltcGxpZmljYXRpb24uIGB0b2wgPSAuMDFgIG1ha2VzIGEgZHJhc3RpYyBkZWNyZWFzZSB0byB0aGUgZmlsZSBzaXplLCBzbyB0aGVyZSBpcyBubyBuZWVkIHRvIGluY3JlYXNlIHRoaXMgdmFsdWUuIA0KDQpOb3csIGxldOKAmXMgcmUtcGxvdCB1c2luZyB0aGUgc2ltcGxpZmllZCBgLnNocGAgZmlsZS4NCg0KYGBge3J9DQpsZ2Euc2hwLmYuc2ltcDEkbGdhX25hbWUgPC0gbGdhLnNocC5mLnNpbXAxJGlkDQptZXJnZS5sZ2EucHJvZmlsZXMyPC1tZXJnZShsZ2Euc2hwLmYuc2ltcDEsIGxnYV9wcm9maWxlc19kYXRhXzIwMTFfcHQxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBieT0ibGdhX25hbWUiLCBhbGwueD1UUlVFKQ0KY2hvcm8uZGF0YS5mcmFtZTI8LW1lcmdlLmxnYS5wcm9maWxlczJbb3JkZXIobWVyZ2UubGdhLnByb2ZpbGVzMiRvcmRlciksIF0NCnA0IDwtIGdncGxvdChkYXRhID0gY2hvcm8uZGF0YS5mcmFtZTIsDQogICAgICAgICAgICAgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLA0KICAgICAgICAgICAgICAgICBmaWxsID0gbm90aWZpY2F0aW9uc19wZXJfMV8wMDBfcGVvcGxlX29mX3BlcnR1c3NpcykpDQpwNCArIGdlb21fcG9seWdvbihjb2xvciA9ICJibGFjayIsIHNpemUgPSAwLjI1KSArDQogIGNvb3JkX21hcCgpICsNCiAgc2NhbGVfZmlsbF9kaXN0aWxsZXIobmFtZSA9ICJDYXNlcyBcbiBwZXIgMSwwMDAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGUgPSAibGVnZW5kIiwNCiAgICAgICAgICAgICAgICAgICAgcGFsZXR0ZSA9ICJZbE9yUmQiLCBkaXJlY3Rpb24gPSAxKSArDQogIHRoZW1lX21pbmltYWwoKSArIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueCAgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ICA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGFuZWwuZ3JpZCAgPSBlbGVtZW50X2JsYW5rKCkpICsNCiAgbGFicyh0aXRsZT0iVmljdG9yaWFuIExHQSBQZXJ0dXNzaXMgQ2FzZXMgLSAyMDExIikNCmBgYA0KDQpOb3csIHdlIHdvdWxkIGJlIGhhcmQtcHJlc3NlZCB0byBub3RpY2UgYSBkaWZmZXJlbmNlLiBUaGlzIGZ1bmN0aW9uIG1heSBzYXZlIHVzIGEgbG90IG9mIHRyb3VibGUgd2hlbiBkZWFsaW5nIHdpdGggcHJlY2lzaW9uICouc2hwKiBmaWxlcyBvciBvcHRpbWlzaW5nIGEgZGF0YSB2aXN1YWxpc2F0aW9uIGFwcCB0byBydW4gc21vb3RobHkgaW4gdGhlIGNsb3VkLg0KDQpBZGQgYSBuZXcgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpJbnNlcnQgQ2h1bmsqIGJ1dHRvbiBvbiB0aGUgdG9vbGJhciBvciBieSBwcmVzc2luZyAqQ3RybCtBbHQrSSouDQoNCldoZW4geW91IHNhdmUgdGhlIG5vdGVib29rLCBhbiBIVE1MIGZpbGUgY29udGFpbmluZyB0aGUgY29kZSBhbmQgb3V0cHV0IHdpbGwgYmUgc2F2ZWQgYWxvbmdzaWRlIGl0IChjbGljayB0aGUgKlByZXZpZXcqIGJ1dHRvbiBvciBwcmVzcyAqQ3RybCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLg0KDQpUaGUgcHJldmlldyBzaG93cyB5b3UgYSByZW5kZXJlZCBIVE1MIGNvcHkgb2YgdGhlIGNvbnRlbnRzIG9mIHRoZSBlZGl0b3IuIENvbnNlcXVlbnRseSwgdW5saWtlICpLbml0KiwgKlByZXZpZXcqIGRvZXMgbm90IHJ1biBhbnkgUiBjb2RlIGNodW5rcy4gSW5zdGVhZCwgdGhlIG91dHB1dCBvZiB0aGUgY2h1bmsgd2hlbiBpdCB3YXMgbGFzdCBydW4gaW4gdGhlIGVkaXRvciBpcyBkaXNwbGF5ZWQuDQo=